using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.SQLite;
using System.Drawing;
using System.Windows.Forms;
using Jonathan.Classes;
using System.Threading;
using System.Collections;
using System.Text;
using Jonathan.Properties;
using Jonathan.Tabber;

namespace Jonathan.Controls
{
   /// <summary>
   /// Adds the search results to the display.
   /// </summary>
   public delegate void DelSetSearchResult ();

   /// <summary>
   /// Class to search through the material in Jonathan.
   /// </summary>
   public partial class CtrlSearch : TabberPage, IWebberHost
   {
      private readonly FrmMain m_FormMain;
      private string m_DbFile;
      private string m_Type;
      private readonly string m_SearchType;
      private readonly DelSetSearchResult m_SetSearchResults;
      private bool m_Loaded;
      private List<string[]> m_SearchResults;
      private string m_ResultsHtml;
      private int m_ResultCount;

      #region - Constructor -

      /// <summary>
      /// Creates a new Search Control...
      /// </summary>
      /// <param name="main">Main form.</param>
      /// <param name="type">Type of search</param>
      public CtrlSearch (FrmMain main, string type)
         : base ("Search")
      {
         this.m_Loaded = false;
         this.m_FormMain = main;
         InitializeComponent ();
         this._WebSearch.SetupWebber (main, this);

         this.m_ResultsHtml = "";
         this.m_ResultCount = 0;
         this.Load += CtrlSearchLoad;
         this.Resize += CtrlSearchResize;
         this.SetEmptyResults ();

         if (this.m_FormMain != null)
         {
            this.m_SearchType = type;
            this.m_cmbVersion.DropDownStyle = ComboBoxStyle.DropDownList;
            this.m_SetSearchResults = new DelSetSearchResult (this.SetSearchResults);

            if (type != Common.TYPE_PASSAGE)
            {
               // Add Bibles
               foreach (CjData.IcDbInfo dbTemp in this.m_FormMain.ProgramData.BibleDatabases)
               {
                  this.m_cmbVersion.Items.Add (dbTemp.Name);
               }
               // Add Other Books
               foreach (CjData.IcDbInfo dbTemp in this.m_FormMain.ProgramData.OtherDatabases)
               {
                  this.m_cmbVersion.Items.Add (dbTemp.Name);
               }
               // Add Reference
               if (this.m_FormMain.ProgramData.ReferenceDatabases.Count > 0)
               {
                  this.m_cmbVersion.Items.Add ("Search " + Common.TYPE_REFERENCE);
               }

               if (type == Common.TYPE_REFERENCE)
               {
                  this.m_cmbVersion.SelectedIndex = this.m_cmbVersion.Items.Count - 1;
               }
               else if (type == Common.TYPE_BIBLE)
               {
                  this.m_cmbVersion.SelectedIndex = this.m_cmbVersion.Items.IndexOf (this.m_FormMain.ProgramData.DefaultBible);
                  this.m_DbFile = this.m_FormMain.DefaultBibleFile;
                  UpdateBookList ();
               }
            }
            else
            {
               this.grpCriteria.Visible = false;
               this.grpRange.Width = this.grpRange.Width + this.grpCriteria.Width + (this.grpRange.Left - this.grpCriteria.Right);
               this.grpRange.Left = grpCriteria.Left;
               this.rdoNewTest.Visible = false;
               this.rdoOldTest.Visible = false;
               this.rdoNone.Checked = true;
               this.m_Type = Common.TYPE_PASSAGE;
               foreach (CjData.IcDbInfo dbTemp in this.m_FormMain.ProgramData.BibleDatabases)
               {
                  this.clbBooks.Items.Add (dbTemp.Name, false);
               }
               int index = this.clbBooks.Items.IndexOf (this.m_FormMain.ProgramData.DefaultBible);
               this.clbBooks.SetItemChecked (index, true);
            }

            this.m_cmbSearch.KeyDown += SearchTextKeyDown;
            this.m_cmbSearch.Focus ();
            this.SetTabText ();
            this.UpdateFont ();
            this._Working.BringToFront ();
         }
      }

      void CtrlSearchResize (object sender, EventArgs e)
      {
         this._Working.Top = this._WebSearch.Bottom - this._Working.Height - 3;
         this._Working.Left = (this.Width / 2) - (this._Working.Width / 2);
      }

      void CtrlSearchLoad (object sender, EventArgs e)
      {
         this.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
         if (m_Loaded)
            this.Search ();
         else
         {
            this.m_Loaded = true;
            this._Working.Visible = false;
         }
      }

      #endregion

      #region -= Get Book Type =-

      /// <summary>
      /// Gets the Type of Book...
      /// </summary>
      private void GetBookType ()
      {
         using (SQLiteConnection dbConn = new SQLiteConnection (Common.ConnString (this.m_DbFile)))
         {
            dbConn.Open ();
            SQLiteCommand command = dbConn.CreateCommand ();
            command.CommandText = "SELECT Type FROM book_info";
            SQLiteDataReader reader = command.ExecuteReader ();
            reader.Read ();
            this.m_Type = reader.GetString (0);
         }
      }

      #endregion

      #region - Update Book List -

      /// <summary>
      /// Updates the list of books to search in...
      /// </summary>
      private void UpdateBookList ()
      {
         this.GetBookType ();
         if (this.m_Type == Common.TYPE_OTHER)
         {
            this.rdoNewTest.Enabled = false;
            this.rdoOldTest.Enabled = false;
         }
         else if (this.m_Type == Common.TYPE_BIBLE)
         {
            this.rdoNewTest.Enabled = true;
            this.rdoOldTest.Enabled = true;
         }

         using (SQLiteConnection dbConn = new SQLiteConnection (Common.ConnString (this.m_DbFile)))
         {
            dbConn.Open ();
            SQLiteCommand command = dbConn.CreateCommand ();
            command.CommandText = "SELECT Name, BookOrder FROM book_list ORDER BY BookOrder";
            SQLiteDataReader reader = command.ExecuteReader ();
            while (reader.Read ())
            {
               this.clbBooks.Items.Add (reader.GetString (0), true);
            }
         }
      }

      #endregion

      #region - Book Selection -

      /// <summary>
      /// Check all the books...
      /// </summary>
      /// <param name="sender">Radio Button</param>
      /// <param name="e">Events</param>
      private void RdoEntireBibleCheckedChanged (object sender, EventArgs e)
      {
         if (this.rdoEntireBible.Checked)
         {
            this.SetAllBooks (true);
         }
      }

      /// <summary>
      /// Check the Old Testament books...
      /// </summary>
      /// <param name="sender">Radio Button</param>
      /// <param name="e">Events</param>
      private void RdoOldTestCheckedChanged (object sender, EventArgs e)
      {
         if (this.rdoOldTest.Checked)
         {
            if (this.clbBooks.Items.Count > 38)
            {
               this.SetAllBooks (false);
               for (int a = 0; a < 39; a++)
               {
                  this.clbBooks.SetItemChecked (a, true);
               }
            }
         }
      }

      /// <summary>
      /// Check the New Testament books...
      /// </summary>
      /// <param name="sender">Radio Button</param>
      /// <param name="e">Events</param>
      private void RdoNewTestCheckedChanged (object sender, EventArgs e)
      {
         if (this.rdoNewTest.Checked)
         {
            if (this.clbBooks.Items.Count > 40)
            {
               this.SetAllBooks (false);
               for (int a = 39; a < this.clbBooks.Items.Count; a++)
               {
                  this.clbBooks.SetItemChecked (a, true);
               }
            }
            else if (this.clbBooks.Items.Count == 27)
            {
               // New Testament only...
               this.SetAllBooks (false);
               for (int a = 0; a < this.clbBooks.Items.Count; a++)
               {
                  this.clbBooks.SetItemChecked (a, true);
               }
            }
         }
      }

      /// <summary>
      /// UnCheck all the books...
      /// </summary>
      /// <param name="sender">Radio Button</param>
      /// <param name="e">Events</param>
      private void RdoNoneCheckedChanged (object sender, EventArgs e)
      {
         if (this.rdoNone.Checked)
         {
            this.SetAllBooks (false);
         }
      }

      /// <summary>
      /// Checks or Unchecks all books...
      /// </summary>
      /// <param name="check">Check State</param>
      private void SetAllBooks (bool check)
      {
         for (int a = 0; a < this.clbBooks.Items.Count; a++)
         {
            this.clbBooks.SetItemChecked (a, check);
         }
      }

      #endregion

      #region - Version -

      /// <summary>
      /// Occurs when version is changed...
      /// </summary>
      /// <param name="sender">ComboBox</param>
      /// <param name="e">Events</param>
      private void MCmbVersionSelectedIndexChanged (object sender, EventArgs e)
      {
         // Clear results...
         this.SetEmptyResults ();

         if (this.m_cmbVersion.Text.Equals ("Search " + Common.TYPE_REFERENCE))
         {
            this.m_Type = Common.TYPE_REFERENCE;
            this.rdoEntireBible.Checked = true;
            this.rdoNewTest.Visible = false;
            this.rdoOldTest.Visible = false;
            this.m_SearchInDef.Visible = true;
            this.clbBooks.Items.Clear ();
            foreach (CjData.IcDbInfo dbTemp in this.m_FormMain.ProgramData.ReferenceDatabases)
            {
               this.clbBooks.Items.Add (dbTemp.Name, true);
            }
         }
         else
         {
            this.rdoNewTest.Visible = true;
            this.rdoOldTest.Visible = true;
            this.m_SearchInDef.Visible = false;

            // Update books...
            this.m_DbFile = this.m_FormMain.GetDbPath (this.m_cmbVersion.Text);
            this.UpdateBookList ();
         }
      }

      /// <summary>
      /// Changes the current version...
      /// </summary>
      /// <param name="version">Version to Change to.</param>
      public void ChangeVersion (string version)
      {
         this.m_cmbVersion.SelectedIndex = this.m_cmbVersion.Items.IndexOf (version);
      }

      #endregion

      #region -= Search =-

      void SearchTextKeyDown (object sender, KeyEventArgs e)
      {
         if (e.KeyCode == Keys.Enter)
         {
            this.MBtnSearchClick (sender, null);
         }
      }

      private void MBtnSearchClick (object sender, EventArgs e)
      {
         this.Search ();
      }

      /// <summary>
      /// Adds the Text in the search field to the combobox...
      /// </summary>
      private void AddSearchText ()
      {
         for (int a = 0; a < this.m_cmbSearch.Items.Count; a++)
         {
            if (this.m_cmbSearch.Text.Equals (this.m_cmbSearch.Items[a].ToString (), StringComparison.CurrentCultureIgnoreCase))
            {
               return;
            }
         }

         this.m_cmbSearch.Items.Add (this.m_cmbSearch.Text);
      }

      /// <summary>
      /// Searches for the given text...
      /// </summary>
      /// <param name="text">string to search for.</param>
      public void Search (string text)
      {
         this.m_cmbSearch.Text = text;
         if (this.m_Loaded)
            this.Search ();
         else
            this.m_Loaded = true;
      }

      /// <summary>
      /// Searches the selected bible for the text...
      /// </summary>
      private void Search ()
      {
         this._Working.SetText ("Searching for " + this.m_cmbSearch.Text.Trim () + Resources.Ellipse);
         this._Working.Visible = true;
         this.SetEmptyResults ();
         this.lblResults.Text = Resources.Search_No_Items;
         if (this.m_cmbSearch.Text.Trim () != string.Empty)
         {
            this.SetTabText ();
            this.AddSearchText ();

            ArrayList data = new ArrayList {this.clbBooks.CheckedItems, this.m_cmbSearch.Text.Trim (), this.m_DbFile};
            if (this.rdoAll.Checked)
               data.Add (Common.SearchCriteria.AllWords);
            else if (this.rdoAny.Checked)
               data.Add (Common.SearchCriteria.AnyWord);
            else
               data.Add (Common.SearchCriteria.Phrase);

            data.Add (this.m_cmbVersion.Text);
            if (this.m_Type == Common.TYPE_REFERENCE)
            {
               Thread t = new Thread (this.SearchReference);
               t.Start (data);
            }
            else if (this.m_Type == Common.TYPE_BIBLE || this.m_Type == Common.TYPE_OTHER)
            {
               Thread t = new Thread (this.SearchBible);
               t.Start (data);
            }
            else
            {
               Thread t = new Thread (this.FindPassages);
               t.Start (data);
            }
         }
      }

      #endregion

      #region -= Find Passages =-

      /// <summary>
      /// Finds Passages...
      /// </summary>
      /// <param name="sourceObj">Data needed to perform find.</param>
      private void FindPassages (object sourceObj)
      {
         ArrayList data = sourceObj as ArrayList;
         if (data != null)
         {
            List<CPassage> passages = Parser.Parse (data[1].ToString ());
            this.m_SearchResults = new List<string[]> ();

            if (passages.Count > 0)
            {
               CheckedListBox.CheckedItemCollection items = data[0] as CheckedListBox.CheckedItemCollection;
               if (items != null)
               {
                  foreach (string version in items)
                  {
                     //string version = data[0].ToString();
                     using (SQLiteConnection dbConn = new SQLiteConnection (Common.ConnString (this.m_FormMain.GetDbPath (version))))
                     {
                        dbConn.Open ();

                        foreach (CPassage passage in passages)
                        {
                           SQLiteCommand command = dbConn.CreateCommand ();
                           command.CommandText = string.Format ("SELECT Verse, Text FROM book_text WHERE Book='{0}' AND Chapter={1}{2}",
                           passage.Book, passage.Chapter,
                           (string.IsNullOrEmpty (passage.Verse)) ? string.Empty : " AND Verse=" + passage.Verse);
                           SQLiteDataReader reader = command.ExecuteReader ();

                           while (reader.Read ())
                           {
                              this.m_SearchResults.Add (new[] { version, passage.Book + " " + passage.Chapter + ":" +
                                                                   reader.GetInt32 (0), reader.GetString (1)
                                                              });
                           }
                        }
                     }
                  }
               }
            }
         }
         if (data != null) this.GroupSearchResults (data[1].ToString ());
      }

      #endregion

      #region -= Search Reference =-

      /// <summary>
      /// Searches Reference...
      /// </summary>
      /// <param name="sourceObj">Data needed for search.</param>
      private void SearchReference (object sourceObj)
      {
         this.m_SearchResults = new List<string[]> ();
         ArrayList data = sourceObj as ArrayList;
         if (data != null)
         {
            CheckedListBox.CheckedItemCollection items = data[0] as CheckedListBox.CheckedItemCollection;
            if (items != null)
            {
               foreach (string source in items)
               {
                  string searchText = data [1].ToString ();

                  string dataPath = "";
                  foreach (CjData.IcDbInfo dbTemp in this.m_FormMain.ProgramData.ReferenceDatabases)
                  {
                     if (dbTemp.Name == source)
                     {
                        dataPath = Common.DataFolder + dbTemp.Path;
                        break;
                     }
                  }


                  using (SQLiteConnection dbConn = new SQLiteConnection (Common.ConnString (dataPath)))
                  {
                     dbConn.Open ();
                     SQLiteCommand command = dbConn.CreateCommand ();
                     command.CommandText = string.Format ("SELECT Word, Text FROM book_text WHERE Word LIKE '{0}'",
                     searchText);
                     SQLiteDataReader reader = command.ExecuteReader ();

                     while (reader.Read ())
                     {
                        string text = reader.GetString (1);
                        if (text.Length > 777)
                        {
                           text = text.Substring (0, 777);
                           for (int a = text.Length - 1; a >= 0; a--)
                           {
                              if (text [a] == '<')
                              {
                                 text = text.Substring (0, a - 1);
                                 break;
                              }
                              if (text [a] == '>')
                              {
                                 break;
                              }
                           }
                           text += Resources.Ellipse;
                        }

                        this.m_SearchResults.Add (new [] { source, reader.GetString (0), text });
                     }
                  }
               }
            }
         }

         this.m_SearchResults.Sort (new RefRowComparer (ListSortDirection.Ascending));
         if (data != null) this.GroupSearchResults (data[1].ToString ());
      }

      #endregion

      #region -= Search Bible =-

      /// <summary>
      /// Searches the Bible...
      /// </summary>
      /// <param name="sourceObj">Array List of needed objects.</param>
      private void SearchBible (object sourceObj)
      {
         this.m_SearchResults = new List<string[]> ();
         ArrayList data = sourceObj as ArrayList;
         if (data != null)
         {
            using (SQLiteConnection dbConn = new SQLiteConnection (Common.ConnString (data [2].ToString ())))
            {
               dbConn.Open ();
               CheckedListBox.CheckedItemCollection items = data [0] as CheckedListBox.CheckedItemCollection;
               if (items != null)
               {
                  foreach (string book in items)
                  {
                     SQLiteCommand command = dbConn.CreateCommand ();
                     command.CommandText =
                        string.Format (
                           "SELECT Chapter, Verse, Text FROM book_text WHERE Book='{0}' AND Text LIKE '%{1}%'",
                           book.Replace ("'", "''"), data[1].ToString ().Replace ("'", "''"));
                     command.Prepare ();
                     SQLiteDataReader dataReader = command.ExecuteReader ();

                     while (dataReader.Read ())
                     {
                        int chapter = dataReader.GetInt32 (dataReader.GetOrdinal ("Chapter"));
                        int verse = dataReader.GetInt32 (dataReader.GetOrdinal ("Verse"));
                        string text = dataReader.GetString (dataReader.GetOrdinal ("Text"));
                        this.m_SearchResults.Add (new []
                                                     {
                                                        book, "<a class=\"goto\" href=\"" + data [4] +
                                                              "\" title=\"Goto " + book + " " + chapter + ":" +
                                                              verse + "\">" + chapter + ":" + verse + "</a>", text
                                                     });
                     }
                  }
               }
               this.GroupSearchResults (data [1].ToString ());
            }
         }
      }

      #endregion

      #region -= Set Tab Text =-

      /// <summary>
      /// Sets the Text of the Tab...
      /// </summary>
      private void SetTabText ()
      {
         string tabText;
         switch (this.m_Type)
         {
            case "Reference":
               tabText = "Reference Search";
               break;
            case "Passage":
               tabText = "Passage Lookup";
               break;
            default:
               tabText = "Search";
               break;
         }
         if (!string.IsNullOrEmpty (this.m_cmbSearch.Text.Trim ()))
         {
            tabText += " | " + this.m_cmbSearch.Text.Trim ();
         }
         this.TabTitle = tabText;
      }

      #endregion

      #region -= Misc =-

      /// <summary>
      /// Delegate Method to display the number of results and finish search...
      /// </summary>
      /// <param name="searchText">Text to search for.</param>
      public void SetSearchResults (string searchText)
      {
         this.m_ResultCount = 1;
         StringBuilder sb = new StringBuilder ();
         foreach (string[] result in this.m_SearchResults)
         {
            if (result[1].Equals ("group"))
            {
               sb.Append ("<tr><th align=\"left\" colspan=\"3\" style=\"border-bottom: 2px soild black\">");
               sb.Append (result[0]);
               sb.Append ("</th></tr>");
            }
            else
            {
               sb.Append ("<tr passage=\"" + result[0] + "|" + Common.RemoveHtml (result[1]) + "\"><td valign=\"top\" align=\"left\" style=\"color:" +
                   ColorTranslator.ToHtml (Color.DarkSlateBlue) + ";\"><sup><em>[");
               sb.Append (this.m_ResultCount + "]</em></sup></td><td class=\"passage\" valign=\"top\" align=\"left\"");
               sb.Append (this.m_SearchType == Common.TYPE_PASSAGE ? " NOWRAP>" : ">");
               sb.Append (result[1]);
               sb.Append ("</td><td>");
               sb.Append (result[2]);
               sb.Append ("</td></tr>");
               this.m_ResultCount++;
            }
         }
         this.m_ResultCount--;
         sb.Append ("</table></div></div></body></html>");
         this.m_ResultsHtml = Common.HighlightHtml (sb.ToString (), searchText, false);
         this.Invoke (this.m_SetSearchResults);
      }

      private void SetSearchResults ()
      {
         if (!string.IsNullOrEmpty (this.m_ResultsHtml))
         {
            StringBuilder sb = new StringBuilder ();
            sb.Append (this.m_FormMain.GetHtmlHeader ());
            sb.Append ("<div id=\"reader\"><div id=\"readerTitles\"><table width=\"100%\"><tr><th align=\"center\" style=\"filter:progid:DXImageTransform.Microsoft.Gradient(endColorstr='#0060A5', startColorstr='#C0CFE2', gradientType='0');color:white;\">");
            sb.Append ("Search Results for " + this.m_cmbSearch.Text.Trim () + "</th></tr></table></div>");
            sb.Append ("<div id=\"innerReader\"><table class=\"search\" width=\"100%\">");
            sb.Append (this.m_ResultsHtml);
            this._WebSearch.HTML = sb.ToString ();
            this.lblResults.Text = (this.m_ResultCount == 1) ? "1 item found." : this.m_ResultCount + " items found.";
         }
         else
            this.SetEmptyResults ();
         this._Working.Visible = false;
      }

      /// <summary>
      /// Groups the Search Results...
      /// </summary>
      private void GroupSearchResults (string searchText)
      {
         string book = "";
         int lastBook = -1;
         int itemCount = 0;
         for (int a = 0; a < this.m_SearchResults.Count; a++)
         {
            string[] result = this.m_SearchResults[a];
            if (!result[0].Equals (book))
            {
               book = result[0];
               string[] group = new string[3];
               group[0] = book;
               group[1] = "group";
               group[2] = "";
               this.m_SearchResults.Insert (a, group);

               if (lastBook != -1)
                  this.m_SearchResults[lastBook][0] = this.m_SearchResults[lastBook][0] + " (" + itemCount + ((itemCount == 1) ? " item" : " items") + ")";

               itemCount = 0;
               lastBook = a;
            }
            else
            {
               itemCount++;
            }
         }
         if (lastBook != -1)
         {
            this.m_SearchResults[lastBook][0] = this.m_SearchResults[lastBook][0] + " (" + itemCount + ((itemCount == 1) ? " item" : " items") + ")";
            this.SetSearchResults (searchText);
         }
         else
            this.Invoke (this.m_SetSearchResults);
      }

      /// <summary>
      /// Sets an Empty Result String...
      /// </summary>
      private void SetEmptyResults ()
      {
         this._WebSearch.HTML = this.m_FormMain.GetHtmlHeader () +
             "<div id=\"reader\"><div id=\"readerTitles\"></div><div id=\"innerReader\"><table width=\"100%\" height=\"100%\"><tr><th>No Results to Display</th></tr></table></div></div></body></html>";
      }

      /// <summary>
      /// Gets Additional Page Info.
      /// </summary>
      /// <returns>Page Info in string.</returns>
      public override string GetPageInfo ()
      {
         //return base.GetPageInfo();
         return this.m_SearchType;
      }

      /// <summary>
      /// A Method to update the Font...
      /// </summary>
      public void UpdateFont ()
      {
         this.SetSearchResults ();
         //this.m_SearchGrid.Font = this.m_FormMain.ProgramData.DefaultFont.ToFont();
      }

      #endregion

      #region - Menu -

      /// <summary>
      /// Occurs when the context menu is opening...
      /// </summary>
      /// <param name="sender">ContextMenuStrip</param>
      /// <param name="e">CancelEventArgs</param>
      void CtxMainOpening (object sender, CancelEventArgs e)
      {
         if (string.IsNullOrEmpty (this._WebSearch.Selection))
         {
            this.copyToolStripMenuItem.Enabled = false;
            this.searchToolStripMenuItem.Enabled = false;
            this.defineToolStripMenuItem.Enabled = false;
            this.searchToolStripMenuItem.Text = "Nothing to Search for...";
            this.defineToolStripMenuItem.Text = "Nothing to Look up...";
         }
         else
         {
            this.copyToolStripMenuItem.Enabled = true;
            this.searchToolStripMenuItem.Enabled = true;
            this.searchToolStripMenuItem.Text = "Search for " + this._WebSearch.Selection.Split (' ')[0] + Resources.Ellipse;
            this.defineToolStripMenuItem.Enabled = true;
            this.defineToolStripMenuItem.Text = "Look up " + this._WebSearch.Selection.Split (' ')[0] + Resources.Ellipse;
         }

         this.gotoChapterToolStripMenuItem.Enabled = false;
         this.copyItemToolStripMenuItem.Enabled = false;
         this.gotoChapterToolStripMenuItem.Text = "Nothing to Goto...";
         HtmlElementCollection hEls = this._WebSearch.Document.GetElementsByTagName ("TR");
         foreach (HtmlElement hEl in hEls)
         {
            if (!string.IsNullOrEmpty (hEl.Style))
            {
               int index = 0;
               string passage = "";
               if ((index = hEl.OuterHtml.IndexOf ("passage=")) != -1)
                  passage = hEl.OuterHtml.Substring (index + 9, hEl.OuterHtml.IndexOf (">") - 10 - index);

               if (!string.IsNullOrEmpty (passage))
               {
                  this.gotoChapterToolStripMenuItem.Enabled = true;
                  this.copyItemToolStripMenuItem.Enabled = true;
                  if (passage.Contains ("|"))
                  {
                     if (this.m_SearchType == Common.TYPE_BIBLE)
                        this.gotoChapterToolStripMenuItem.Text = Resources.Goto + passage.Replace ('|', ' ') + Resources.Ellipse;
                     else
                        this.gotoChapterToolStripMenuItem.Text = Resources.Goto + passage.Split ('|')[1] + Resources.Ellipse;
                  }
                  else
                  {
                     this.gotoChapterToolStripMenuItem.Text = "Goto item...";
                  }
                  break;
               }
            }
         }
      }

      /// <summary>
      /// Copies the selected Text...
      /// </summary>
      /// <param name="sender">ToolStripMenuItem</param>
      /// <param name="e">Events</param>
      void CopyClick (object sender, EventArgs e)
      {
         this._WebSearch.Copy ();
      }

      /// <summary>
      /// Copies the selected item...
      /// </summary>
      /// <param name="sender">ToolStripMenuItem</param>
      /// <param name="e">Events</param>
      void CopyItemClick (object sender, EventArgs e)
      {
         if (this._WebSearch.Document != null)
         {
            HtmlElementCollection hEls = this._WebSearch.Document.GetElementsByTagName ("TR");
            string copyText = "";
            foreach (HtmlElement hEl in hEls)
            {
               if (!string.IsNullOrEmpty (hEl.Style))
               {
                  int index;
                  string passage = "";
                  if ((index = hEl.OuterHtml.IndexOf ("passage=")) != -1)
                     passage = hEl.OuterHtml.Substring (index + 9, hEl.OuterHtml.IndexOf (">") - 10 - index);
                  if (!string.IsNullOrEmpty (copyText))
                     copyText += "\r\n";

                  if (!string.IsNullOrEmpty (passage))
                  {
                     switch (this.m_SearchType)
                     {
                        case Common.TYPE_BIBLE:
                           {
                              copyText += passage.Replace ('|', ' ') + " - ";
                              copyText += hEl.Children [2].InnerText;
                           }
                           break;
                        case Common.TYPE_PASSAGE:
                           {
                              copyText += passage + " - ";
                              copyText += hEl.Children [2].InnerText;
                           }
                           break;
                        case Common.TYPE_REFERENCE:
                           {
                              copyText += passage + " - ";
                              copyText += hEl.Children [2].InnerText;
                           }
                           break;
                     }
                  }
               }
            }

            if (!string.IsNullOrEmpty (copyText))
               Clipboard.SetText (copyText);
         }
      }

      /// <summary>
      /// Searches for the selected item...
      /// </summary>
      /// <param name="sender">ToolStripMenuItem</param>
      /// <param name="e">Events</param>
      void SearchClick (object sender, EventArgs e)
      {
         this.m_FormMain.Search (
            this.m_SearchType == Common.TYPE_BIBLE ? this.m_cmbVersion.Text : this.m_FormMain.ProgramData.DefaultBible,
            this._WebSearch.Selection, this);
      }

      /// <summary>
      /// Defines the selected item...
      /// </summary>
      /// <param name="sender">ToolStripMenuItem</param>
      /// <param name="e">Events</param>
      void DefineClick (object sender, EventArgs e)
      {
         this.m_FormMain.Search (this._WebSearch.Selection, Common.TYPE_REFERENCE, this);
      }

      /// <summary>
      /// Selects all the items...
      /// </summary>
      /// <param name="sender">ToolStripMenuItem</param>
      /// <param name="e">Events</param>
      void SelectAllClick (object sender, EventArgs e)
      {
         if (this._WebSearch.Document != null)
         {
            HtmlElementCollection hEls = this._WebSearch.Document.GetElementsByTagName ("TR");
            foreach (HtmlElement hEl in hEls)
            {
               if (hEl.FirstChild != null)
               {
                  if (!hEl.FirstChild.TagName.Equals ("TH"))
                  {
                     hEl.Style = "background: #C0CFE2;";
                  }
               }
            }
         }
      }

      /// <summary>
      /// Goes to the selected item...
      /// </summary>
      /// <param name="sender">ToolStripMenuItem</param>
      /// <param name="e">Events</param>
      void GotoClick (object sender, EventArgs e)
      {
         if (this._WebSearch.Document != null)
         {
            HtmlElementCollection hEls = this._WebSearch.Document.GetElementsByTagName ("TR");
            List <CPassage> passages = new List <CPassage> ();
            foreach (HtmlElement hEl in hEls)
            {
               if (!string.IsNullOrEmpty (hEl.Style))
               {
                  int index;
                  string passage = "";
                  if ((index = hEl.OuterHtml.IndexOf ("passage=")) != -1)
                     passage = hEl.OuterHtml.Substring (index + 9, hEl.OuterHtml.IndexOf (">") - 10 - index);

                  if (!string.IsNullOrEmpty (passage))
                  {
                     switch (this.m_SearchType)
                     {
                        case Common.TYPE_BIBLE:
                           {
                              if (this.m_Type == Common.TYPE_OTHER)
                              {
                                 CPassage p = new CPassage
                                                 {
                                                    Book = passage.Split ('|') [0],
                                                    Chapter = passage.Split ('|') [1].Split (':') [0],
                                                    Verse = passage.Split ('|') [1].Split (':') [1],
                                                    Version = this.m_cmbVersion.Text
                                                 };
                                 passages.Add (p);
                              }
                              else
                              {
                                 List <CPassage> passes = Parser.Parse (passage.Replace ('|', ' '));
                                 foreach (CPassage pass in passes)
                                    pass.Version = this.m_cmbVersion.Text;

                                 passages.AddRange (passes);
                              }
                           }
                           break;
                        case Common.TYPE_PASSAGE:
                           {
                              List <CPassage> passes = Parser.Parse (passage.Split ('|') [1]);
                              foreach (CPassage pass in passes)
                                 pass.Version = passage.Split ('|') [0];

                              passages.AddRange (passes);
                           }
                           break;
                        case Common.TYPE_REFERENCE:
                           {
                              bool added = false;
                              foreach (CPassage tempPass in passages)
                              {
                                 if (tempPass.Version.Equals (passage.Split ('|') [0]))
                                 {
                                    added = true;
                                    tempPass.Book += "|" + passage.Split ('|') [1];
                                    break;
                                 }
                              }
                              if (!added)
                              {
                                 CPassage pass = new CPassage
                                                    {Version = passage.Split ('|') [0], Book = passage.Split ('|') [1]};
                                 passages.Add (pass);
                              }
                           }
                           break;
                     }
                  }
               }
            }

            if (this.m_SearchType == Common.TYPE_REFERENCE)
            {
               foreach (CPassage tempPass in passages)
               {
                  this.m_FormMain.StartReference (tempPass.Version, tempPass.Book.Split ('|'), this);
               }
            }
            else
            {
               this.m_FormMain.StartBible (passages, this);
            }
         }
      }

      #endregion

      private void BtnShowHideClick (object sender, EventArgs e)
      {
         if (this._btnShowHide.ButtonText.Equals ("Less"))
         {
            this._btnShowHide.ButtonText = "More";
            this.grpSearch.Height = 75;
         }
         else
         {
            this._btnShowHide.ButtonText = "Less";
            this.grpSearch.Height = 200;
         }
      }

      #region IWebberHost Members

      public bool SelectRefWord (string word, bool tryContains)
      {
         return true;
      }

      public ContextMenuStrip GetContextMenu ()
      {
         return this.ctxMain;
      }

      public string Book
      {
         get { return ""; }
      }

      public string GetVersion (int version)
      {
         return "";
      }

      public string GetVersionPath (int version)
      {
         return "";
      }

      public TabberPage GetTabPage ()
      {
         return this;
      }

      #endregion
   }
}
